﻿/////////////////////////////////////////////////////////////////////////////////////////////
// <copyright file="OutlookLiveMailBox.cs" company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
/////////////////////////////////////////////////////////////////////////////////////////////

namespace Microsoft.LiveAtEdu.Samples.Powershell.OutlookLive
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Management.Automation;

    /// <summary>
    /// Powershell commands for Mailbox.
    /// </summary>
    public class OutlookLiveMailBox
    {
        /// <summary>
        /// Session runspace instance.
        /// </summary>
        private readonly SessionRunspace sessionRunspace;

        /// <summary>
        /// Initializes a new instance of the OutlookLiveMailBox class.
        /// </summary>
        /// <param name="sessionRunspace">Session runspace instance.</param>
        public OutlookLiveMailBox(SessionRunspace sessionRunspace)
        {
            if (sessionRunspace == null)
            {
                throw new ArgumentOutOfRangeException("sessionRunspace");
            }

            this.sessionRunspace = sessionRunspace;
        }

        /// <summary>
        /// Method to create user account in outlook live
        /// </summary>
        /// <param name="firstName">First name.</param>
        /// <param name="lastName">Last name.</param>
        /// <param name="displayName">Display name.</param>
        /// <param name="windowsLiveId">Windows live id.</param>
        /// <param name="password">User password.</param>
        /// <returns>Return true(pass) / false(fail)</returns>
        public bool CreateMailBox(string firstName, string lastName, string displayName, string windowsLiveId, string password)
        {
            // Get unique name from Windows live Id.
            string name = windowsLiveId.Substring(0, windowsLiveId.IndexOf("@"));

            var command = new PSCommand();
            command.AddScript(string.Format(MailBoxScripts.CreateMailBoxScript, name, password, windowsLiveId, firstName, lastName, displayName));

            var accounts = this.sessionRunspace.ExecuteCommand(command);

            if (accounts != null && accounts.Count == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Method to import accounts
        /// </summary>
        /// <param name="filePath">Path to file containing accounts.</param>
        /// <returns>True if operaion is successful.</returns>
        public bool ImportAccounts(string filePath)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(MailBoxScripts.ImportAccountScript.Replace("{0}", filePath));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Disable MailBox of user
        /// </summary>
        /// <param name="identity">windows live id</param>
        /// <param name="isEnabled">Specifies flag to indicate enable/disable.</param>
        /// <returns>True if operation is success, else false.</returns>
        public bool DisableMailBox(string identity, bool isEnabled)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.DisableMailBoxScript, identity, isEnabled.ToString()));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Method that gets MailBox Statistices for users based of size filter.
        /// </summary>
        /// <param name="mailboxSizeLimitInBytes">Mailbox Size Limit In Bytes</param>
        /// <param name="filter">filter expressions</param>
        /// <returns>List of mailbox statistics.</returns>
        public List<MailBoxStat> GetMailboxStat(int mailboxSizeLimitInBytes, string filter)
        {
            // Possible filters: ">", "<", "=", "all"
            var mailBoxStatList = new List<MailBoxStat>();

            try
            {
                // By default get all mailboxes
                var command = new PSCommand();
                command.AddScript(MailBoxScripts.GetMailboxesOfAllSize);

                // Get mailboxes of specified size
                if (!filter.Equals("all"))
                {
                    command.AddScript(MailBoxScripts.GetMailboxesOfSpecifiedSize.Replace("{0}", "-" + filter).Replace("{1}", mailboxSizeLimitInBytes.ToString()));
                }

                var mailStatistics = this.sessionRunspace.ExecuteCommand(command);

                foreach (PSObject obj in mailStatistics)
                {
                    PSObject mailbox = this.GetMailbox(obj.Members[Constants.Identity].Value.ToString());
                    PSObject owaEnabled = this.GetCASMailbox(obj.Members[Constants.Identity].Value.ToString());

                    bool isEnabled = false;
                    string displayName = string.Empty;
                    string totalItemSize = string.Empty;
                    string identity = string.Empty;
                    string storageLimitStatus = string.Empty;
                    string windowsLiveId = string.Empty;
                    DateTime lastLogonTime = DateTime.MinValue;

                    if (obj.Members[Constants.DisplayName].Value != null)
                    {
                        displayName = obj.Members[Constants.DisplayName].Value.ToString();
                    }

                    int sizeInBytes = 0;
                    if (obj.Members[Constants.TotalItemSize].Value != null)
                    {
                        totalItemSize = obj.Members[Constants.TotalItemSize].Value.ToString();
                        int startIndex = totalItemSize.IndexOf('(');
                        sizeInBytes = Convert.ToInt32(totalItemSize.Substring(startIndex + 1, (totalItemSize.Length - 8) - startIndex).Replace(",", string.Empty));
                    }

                    if (obj.Members[Constants.Identity].Value != null)
                    {
                        identity = obj.Members[Constants.Identity].Value.ToString();
                    }

                    if (owaEnabled.Members[Constants.OwaEnabled].Value != null)
                    {
                        isEnabled = (bool)owaEnabled.Members[Constants.OwaEnabled].Value;
                    }

                    if (obj.Members[Constants.StorageLimitStatus].Value != null)
                    {
                        storageLimitStatus = obj.Members[Constants.StorageLimitStatus].Value.ToString();
                    }

                    if (mailbox.Members[Constants.WindowsLiveId].Value != null)
                    {
                        windowsLiveId = mailbox.Members[Constants.WindowsLiveId].Value.ToString();
                    }

                    if (obj.Members[Constants.LastLogonTime].Value != null)
                    {
                        lastLogonTime = (DateTime)obj.Members[Constants.LastLogonTime].Value;
                    }

                    mailBoxStatList.Add(new MailBoxStat(
                        displayName,
                        totalItemSize,
                        sizeInBytes,
                        identity,
                        isEnabled,
                        storageLimitStatus,
                        windowsLiveId,
                        lastLogonTime));
                }                
            }
            catch
            {
                // Ignore
            }

            return mailBoxStatList;
        }

        /// <summary>
        /// Gets Mailbox information for user.
        /// </summary>
        /// <param name="identity">Alias of user.</param>
        /// <returns>powershell object containing user info.</returns>
        public PSObject GetMailbox(string identity)
        {
            var command = new PSCommand();
            command.AddScript(string.Format(MailBoxScripts.GetMailBoxScript, identity));
            return this.sessionRunspace.ExecuteCommand(command)[0];
        }

        /// <summary>
        /// Get CAS mailbox
        /// </summary>
        /// <param name="identity">windows live id</param>
        /// <returns>Powershell object response.</returns>
        public PSObject GetCASMailbox(string identity)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            var command = new PSCommand();
            command.AddScript(string.Format(MailBoxScripts.GetCASMailboxScript, identity));
            return this.sessionRunspace.ExecuteCommand(command)[0];
        }

        /// <summary>
        /// Gets primary smtp email address.
        /// </summary>
        /// <param name="identity">Alias of the user</param>
        /// <returns>primary smtp address.</returns>
        public string GetPrimaryEmailAddress(string identity)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            var command = new PSCommand();
            command.AddScript(string.Format(MailBoxScripts.GetMailBoxScript, identity));
            var result = this.sessionRunspace.ExecuteCommand(command);
            return result[0].Members[Constants.PrimarySmtpAddress].Value.ToString();
        }

        /// <summary>
        /// Update primary smtp address for user.
        /// </summary>
        /// <param name="identity">windows live id</param>
        /// <param name="newEmailAddress">new email address</param>
        /// <returns>true if success</returns>
        public bool UpdatePrimaryEmailAddress(string identity, string newEmailAddress)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            try
            {
                string script = this.GetUpdatePrimaryEmaillAddressScript(identity, newEmailAddress);

                var command = new PSCommand();
                command.AddScript(script);
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Remove admin's permission to create rules for user's inbox.
        /// </summary>
        /// <param name="userIdentity">identity of user</param>
        /// <param name="adminIdentity">identity of admin</param>
        /// <returns>true if success</returns>
        public bool RemoveMailboxPermission(string userIdentity, string adminIdentity)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.RemoveMailboxPermissionScript, userIdentity, adminIdentity));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// This method gives admin permission to create inbox rules
        /// on the behalf of specified user.
        /// </summary>
        /// <param name="userIdentity">identity of user</param>
        /// <param name="adminIdentity">identity of admin</param>
        /// <returns>true if success</returns>
        public bool AddMailboxPermission(string userIdentity, string adminIdentity)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.AddMailboxPermission, userIdentity, adminIdentity));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Add proxy mail address
        /// </summary>
        /// <param name="identity">windows live id</param>
        /// <param name="emailAddress">user's email address</param>        
        /// <returns>true if success</returns>
        public bool AddProxyEmailAddress(string identity, string emailAddress)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.AddProxyEmailAddressScript, identity, emailAddress));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Admin creates a rule to redirect user's mail to another mailbox.
        /// </summary>
        /// <param name="ruleName">Name of the rule</param>
        /// <param name="userIdentity">windows live id</param>
        /// <param name="redirectAddress">email id to which user wants to redirect mail.</param>
        /// <returns>true if success</returns>
        public bool NewInboxRuleRedirectMail(string ruleName, string userIdentity, string redirectAddress)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.RedirectMailScript, ruleName, userIdentity, redirectAddress));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Method that resets user password
        /// </summary>
        /// <param name="mailBoxName">Name of mailbox.</param>
        /// <param name="password">New password</param>
        /// <returns>true if success</returns>
        public bool ResetPwd(string mailBoxName, string password)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.ResetPasswordScript, mailBoxName, password));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Admin deletes a rule
        /// </summary>
        /// <param name="ruleIdentity">identity of rule</param>
        /// <returns>true if success</returns>
        public bool RemoveRule(string ruleIdentity)
        {
            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.RemoveRuleScript, ruleIdentity));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Method to set block emails from sender
        /// </summary>
        /// <param name="identity">ID of the recipient</param>
        /// <param name="rejectUserId">ID of the sender</param>
        /// <returns>true if success</returns>
        public bool SetRejectMessagesFrom(string identity, string rejectUserId)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            try
            {
                var command = new PSCommand();
                command.AddScript(string.Format(MailBoxScripts.SetRejectMessagesFromScript, identity, rejectUserId));
                this.sessionRunspace.ExecuteCommand(command);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Gets List of Email Addresses
        /// </summary>
        /// <param name="identity">windows live id</param>
        /// <returns>list of email addresses.</returns>
        public Collection<string> GetEmailAddresses(string identity)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            var emailAddresses = new Collection<string>();

            PSObject mailbox = this.GetMailbox(identity);
            string emailAddress = mailbox.Members[Constants.EmailAddresses].Value.ToString() + " ";

            while (emailAddress.IndexOf(':') != -1)
            {
                int startIndex = emailAddress.IndexOf(':') + 1;
                int endIndex = emailAddress.IndexOf(' ', startIndex);
                int length = endIndex - startIndex;
                emailAddresses.Add(emailAddress.Substring(startIndex, length));
                emailAddress = emailAddress.Substring(endIndex + 1);
            }

            return emailAddresses;
        }

        /// <summary>
        /// Get the primary email address of user.
        /// </summary>
        /// <param name="identity">windows mail id</param>
        /// <param name="newEmailAddress">new email address</param>
        /// <returns>Updated email addresses.</returns>
        public string GetUpdatePrimaryEmaillAddressScript(string identity, string newEmailAddress)
        {
            if (string.IsNullOrEmpty(identity))
            {
                throw new ArgumentOutOfRangeException("identity");
            }

            Collection<string> emailAddresses = this.GetEmailAddresses(identity);
            string script = string.Format(MailBoxScripts.UpdatePrimaryEmaillAddressScript, identity, newEmailAddress);

            foreach (string emailAddress in emailAddresses)
            {
                if (!emailAddress.Equals(newEmailAddress, StringComparison.CurrentCultureIgnoreCase))
                {
                    script = script + ", " + emailAddress;
                }
            }

            return script;
        }
    }
}
